package com.ym.medical.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ym.medical.domain.bo.msg.MiniTemplate;
import com.ym.medical.domain.bo.msg.MpTemplate;
import com.ym.medical.domain.bo.msg.MpTemplateParam;
import com.ym.medical.domain.bo.msg.TemplateParam;
import com.ym.medical.enums.PlaformSourceEnum;
import com.ym.medical.enums.WxMsgTypeEnum;
import com.ym.medical.service.IWxTemplateMsgSV;
import com.ym.medical.service.IWxUserSV;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @Author: DaiKuangYin
 * @Date: 2020/1/14 11:37
 * 微信模板消息 订阅消息
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class WxTemplateMsgSVImpl implements IWxTemplateMsgSV {
    private static final Logger LOGGER = LoggerFactory.getLogger(WxTemplateMsgSVImpl.class);

    @Value("${wx.miniapp.appid}")
    private String maAppId;

    @Value("${wx.miniapp.secret}")
    private String maSecret;

    @Value("${wx.mp.appId}")
    private String mpAppId;

    @Value("${wx.mp.secret}")
    private String mpSecret;

    @Value("${wx.msg.miniState}")
    private String miniState;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IWxUserSV wxUserSV;

    private String getToken(String appId, String secret) {
        ResponseEntity<JSONObject> forEntity = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + secret, JSONObject.class);
        return forEntity.getBody().getString("access_token");
    }

    /**
     * 发送 小程序订阅消息
     *
     * @param openId     发送给谁
     * @param templateId 发送模板
     * @param data       发送数据
     * @param page       跳转页面
     * @return
     */
    @Override
    @Async
    public void sendMiniTemplateWxMsg(String openId, String templateId, List<TemplateParam> data, String page) {
        try {
            MiniTemplate template = new MiniTemplate(openId, templateId, page, data, miniState);
            //获取token
            String accessToken = getToken(maAppId, maSecret);
            //发送消息
            String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
            LOGGER.info("微信开始推送发送参数：{}; 请求地址： {}", template, requestUrl);
            String resData = restTemplate.postForObject(requestUrl, template.toJSON(), String.class);
            LOGGER.info("发送小程序订阅消息成功：{}", resData);
        } catch (Exception e) {
            LOGGER.info("发送小程序订阅消息失败: {}", e.getMessage());
        }
    }


    /**
     * 发送 公众号模板消息
     *
     * @param openId     发送给谁
     * @param templateId 发送模板
     * @param data       发送数据
     * @param page       跳转页面
     * @return
     */
    @Override
    @Async
    public void sendMpTemplateWxMsg(String openId, String templateId, List<MpTemplateParam> data, String page) {
        try {
            MpTemplate template = new MpTemplate(openId, templateId, page, mpAppId, data);
            //获取token
            String accessToken = getToken(mpAppId, mpSecret);
            //发送消息
            String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
            LOGGER.info("微信开始推送发送参数：{}; 请求地址： {}", template, requestUrl);
            String resData = restTemplate.postForObject(requestUrl, template.toJSON(), String.class);
            LOGGER.info("发送公众号模板消息成功：{}", resData);
        } catch (Exception e) {
            LOGGER.info("发送公众号模板消息失败: {}", e.getMessage());
        }
    }


    /**
     * 发送指定类型的消息
     *
     * @param wxMsgTypeEnum
     * @param userId
     * @param params
     */
    @Override
    public void sendWxMsgByType(WxMsgTypeEnum wxMsgTypeEnum, Long userId, String... params) {
        String templateId = wxMsgTypeEnum.getTemplateId();
        String page = wxMsgTypeEnum.getPage();
        PlaformSourceEnum plaformSourceEnum = wxMsgTypeEnum.getPlaformSourceEnum();
        String openId = wxUserSV.getOpenId(userId, plaformSourceEnum);

        switch (plaformSourceEnum) {
            case SMALL_PROGRAM:
                List<TemplateParam> miniParam = TemplateParam.generateTemplateParam(wxMsgTypeEnum, params);
                sendMiniTemplateWxMsg(
                        openId,
                        templateId,
                        miniParam,
                        page);
                break;
            case THE_PUBLIC:
                List<MpTemplateParam> mpParam = MpTemplateParam.generateTemplateParam(wxMsgTypeEnum, params);
                sendMpTemplateWxMsg(
                        openId,
                        templateId,
                        mpParam,
                        page);
                break;
        }
    }

    @Override
    public void sendReplyMsg(PlaformSourceEnum plaformSourceEnum, Long userId, String page, String... params) {
        WxMsgTypeEnum wxMsgTypeEnum;
        if (PlaformSourceEnum.SMALL_PROGRAM.getKey().equals(plaformSourceEnum.getKey())) {
            wxMsgTypeEnum = WxMsgTypeEnum.MINI_DOCTOR_REPLY_MSG;
        } else {
            wxMsgTypeEnum = WxMsgTypeEnum.MP_DOCTOR_REPLY_MSG;
        }
        if (StrUtil.isNotBlank(page)) {
            wxMsgTypeEnum.setPage(page);
        }
        sendWxMsgByType(wxMsgTypeEnum, userId, params);
    }

    @Override
    public void sendEvaluateMsg(PlaformSourceEnum plaformSourceEnum, Long userId, String page, String... params) {
        WxMsgTypeEnum wxMsgTypeEnum;
        if (PlaformSourceEnum.SMALL_PROGRAM.getKey().equals(plaformSourceEnum.getKey())) {
            wxMsgTypeEnum = WxMsgTypeEnum.MINI_INQUIRY_EVALUATE_MSG;
        } else {
            wxMsgTypeEnum = WxMsgTypeEnum.MP_INQUIRY_EVALUATE_MSG;
        }
        if (StrUtil.isNotBlank(page)) {
            wxMsgTypeEnum.setPage(page);
        }
        sendWxMsgByType(wxMsgTypeEnum, userId, params);
    }

    @Override
    public void sendSummaryMsg(PlaformSourceEnum plaformSourceEnum, Long userId, String page, String... params) {
        WxMsgTypeEnum wxMsgTypeEnum;
        if (PlaformSourceEnum.SMALL_PROGRAM.getKey().equals(plaformSourceEnum.getKey())) {
            wxMsgTypeEnum = WxMsgTypeEnum.MINI_INQUIRY_SUMMARY_MSG;
        } else {
            wxMsgTypeEnum = WxMsgTypeEnum.MP_INQUIRY_SUMMARY_MSG;
        }
        if (StrUtil.isNotBlank(page)) {
            wxMsgTypeEnum.setPage(page);
        }
        sendWxMsgByType(wxMsgTypeEnum, userId, params);
    }

    @Override
    public void sendTopicMsg(PlaformSourceEnum plaformSourceEnum, Long userId, String page, String... params) {
        WxMsgTypeEnum wxMsgTypeEnum;
        if (PlaformSourceEnum.SMALL_PROGRAM.getKey().equals(plaformSourceEnum.getKey())) {
            wxMsgTypeEnum = WxMsgTypeEnum.MINI_TOPIC_REMINDER_MSG;
        } else {
            wxMsgTypeEnum = WxMsgTypeEnum.MP_TOPIC_REMINDER_MSG;
        }
        if (StrUtil.isNotBlank(page)) {
            wxMsgTypeEnum.setPage(page);
        }
        sendWxMsgByType(wxMsgTypeEnum, userId, params);
    }

    @Override
    public void sendPayMsg(PlaformSourceEnum plaformSourceEnum, Long userId, String... params) {
        WxMsgTypeEnum wxMsgTypeEnum;
        if (PlaformSourceEnum.SMALL_PROGRAM.getKey().equals(plaformSourceEnum.getKey())) {
            wxMsgTypeEnum = WxMsgTypeEnum.MINI_PAY_MSG;
        } else {
            wxMsgTypeEnum = WxMsgTypeEnum.MP_PAY_MSG;
        }
        sendWxMsgByType(wxMsgTypeEnum, userId, params);

    }

    @Override
    public void sendRefundMsg(PlaformSourceEnum plaformSourceEnum, Long userId, String... params) {
        WxMsgTypeEnum wxMsgTypeEnum;
        if (PlaformSourceEnum.SMALL_PROGRAM.getKey().equals(plaformSourceEnum.getKey())) {
            wxMsgTypeEnum = WxMsgTypeEnum.MINI_REFUND_MSG;
        } else {
            wxMsgTypeEnum = WxMsgTypeEnum.MP_REFUND_MSG;
        }
        sendWxMsgByType(wxMsgTypeEnum, userId, params);
    }

    @Override
    public void sendPhoneInquiryMsg(PlaformSourceEnum plaformSourceEnum, Long userId, String page, String... params) {
        WxMsgTypeEnum wxMsgTypeEnum;
        if (PlaformSourceEnum.SMALL_PROGRAM.getKey().equals(plaformSourceEnum.getKey())) {
            wxMsgTypeEnum = WxMsgTypeEnum.MINI_REFUND_MSG;
        } else {
            wxMsgTypeEnum = WxMsgTypeEnum.MP_REFUND_MSG;
        }
        sendWxMsgByType(wxMsgTypeEnum, userId, params);
    }


    @Override
    public void sendOrderException(PlaformSourceEnum plaformSourceEnum, Long userId, String page, String... params) {
        WxMsgTypeEnum wxMsgTypeEnum;
        if (PlaformSourceEnum.SMALL_PROGRAM.getKey().equals(plaformSourceEnum.getKey())) {
            wxMsgTypeEnum = WxMsgTypeEnum.MINI_ORDER_EXCEPTION_MSG;
        } else {
            wxMsgTypeEnum = WxMsgTypeEnum.MP_ORDER_EXCEPTION_MSG;
        }
        if (StrUtil.isNotBlank(page)) {
            wxMsgTypeEnum.setPage(page);
        }
        sendWxMsgByType(wxMsgTypeEnum, userId, params);
    }
}
